package com.fuhe.chen.vendingmachine.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.fuhe.chen.vendingmachine.common.MachineCache;
import com.fuhe.chen.vendingmachine.common.Utils;
import com.fuhe.chen.vendingmachine.constant.MessageConstant;
import com.fuhe.chen.vendingmachine.dao.BookOrderDao;
import com.fuhe.chen.vendingmachine.dao.ContainerDao;
import com.fuhe.chen.vendingmachine.dao.RefundApplyDao;
import com.fuhe.chen.vendingmachine.dto.BookOrderStatus;
import com.fuhe.chen.vendingmachine.dto.UserDto;
import com.fuhe.chen.vendingmachine.dto.cond.BookOrderCond;
import com.fuhe.chen.vendingmachine.pojo.*;
import com.fuhe.chen.vendingmachine.service.IBookOrderService;
import com.fuhe.chen.vendingmachine.service.ICommodityService;
import com.fuhe.chen.vendingmachine.service.IMQTTService;
import com.fuhe.chen.vendingmachine.service.IUserService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

import static com.fuhe.chen.vendingmachine.constant.MessageConstant.BookOrder.*;

@Service
public class BookOrderServiceImpl implements IBookOrderService {

    @Autowired
    BookOrderDao bookOrderDao;

    @Autowired
    RefundApplyDao refundApplyDao;

    @Autowired
    ICommodityService commodityService;

    @Autowired
    ContainerDao containerDao;

    @Autowired
    IUserService userService;

    @Autowired
    IMQTTService imqttService;

    @Override
    @Transactional
    public BookOrder addBookOrder(String user_id, Float amount, Integer machine_id,String comment, List<JSONObject> commodities) {
        BookOrder bookOrder = new BookOrder();

        //自动生成订单号
        String tradeNo = Utils.getOrderIdByTime();
        bookOrder.setId(tradeNo);
        bookOrder.setUser_id(user_id);
        bookOrder.setAmount(amount);
        bookOrder.setOrder_status(0);
        bookOrder.setMachine_id(machine_id);
        bookOrder.setCreate_date(String.valueOf(System.currentTimeMillis()));
        bookOrder.setComment(comment);
        bookOrderDao.addBookOrder(bookOrder);

        for (JSONObject commodity : commodities) {
            RelationshipBookCommodity relationshipBookCommodity = new RelationshipBookCommodity();
            relationshipBookCommodity.setCommodity_id(commodity.getInteger("id"));
            relationshipBookCommodity.setBook_order_id(tradeNo);
            relationshipBookCommodity.setSpecifications(commodity.getString("specification"));
            relationshipBookCommodity.setCount(commodity.getInteger("count"));
            relationshipBookCommodity.setPrice(commodity.getFloat("price"));

            bookOrderDao.addBookCommodity(relationshipBookCommodity);
        }

        return bookOrder;
    }

    @Override
    public PageInfo<BookOrder> queryOrderByUserId(String userId, Integer status,String orderId,int pageNum,int pageSize) {
        PageHelper.startPage(pageNum,pageSize);
        List<BookOrder> orderByUserId = bookOrderDao.findOrderByUserId(userId, status,orderId==null?null:"%"+orderId+"%");
        PageInfo<BookOrder> pageInfo = new PageInfo<>(orderByUserId);
        return pageInfo;
    }

    @Override
    public PageInfo<BookOrder> queryOrderByCondition(BookOrderCond cond,int pageNum,int pageSize) {
        PageHelper.startPage(pageNum,pageSize);
        List<BookOrder> bookOrders = bookOrderDao.findOrderByCondition(cond);
        PageInfo<BookOrder> bookOrderPageInfo = new PageInfo<>(bookOrders);
        return bookOrderPageInfo;
    }

    @Override
    public BookOrder queryOrderByOrderId(String orderId) {
        BookOrder orderByOrderId = bookOrderDao.findOrderByOrderId(orderId);
        if(orderByOrderId==null){
            return null;
        }
        List<BookCommodity> commodities = bookOrderDao.findBookCommodity(orderId);
        orderByOrderId.setCommodities(commodities);
        return orderByOrderId;
    }

    @Override
    public BookOrder queryOrderByOrderIdForAdmin(String orderId) {
        BookOrder bookOrder = queryOrderByOrderId(orderId);
        if(bookOrder!=null){
            String user_id = bookOrder.getUser_id();
            User byId = userService.findById(user_id);
            UserDto userDto = new UserDto();
            userDto.setId(byId.getId());
            userDto.setName(byId.getName());
            userDto.setNickname(byId.getNickname());
            userDto.setPhone(byId.getPhone());
            bookOrder.setUser(userDto);
        }
        return bookOrder;
    }

    @Override
    public void payBookOrder(String bookOrderId, Integer pay_method, String buyer_id, String pay_order_id) {
        BookOrder bookOrder = new BookOrder();
        bookOrder.setId(bookOrderId);
        bookOrder.setPay_method(pay_method);
        bookOrder.setOrder_status(1);
        bookOrder.setBuyer_id(buyer_id);
        bookOrder.setPay_order_id(pay_order_id);
        bookOrder.setPay_date(String.valueOf(System.currentTimeMillis()));

        bookOrderDao.updateBookOrder(bookOrder);
    }

    @Transactional
    @Override
    public void takeBookOrderCommodity(BookOrder bookOrder) {
        bookOrder.setOrder_status(3);
        bookOrderDao.updateBookOrder(bookOrder);

        containerDao.updateStatus(bookOrder.getContainer_number(),bookOrder.getMachine_id(),0);
    }

    @Transactional
    @Override
    public String addOrderCommodity(Integer machineID, String bookOrderID, String containerNumber) {
        //订单id检测
        BookOrder bookOrder = bookOrderDao.findOrderByOrderId(bookOrderID);
        String result = checkOrderId(machineID, bookOrder);
        if (result != null) return result;

        //生成机器取货码
        String pickCode = Utils.getPickCode(containerNumber);

        bookOrder.setOrder_status(2);
        bookOrder.setContainer_number(containerNumber);
        bookOrder.setPick_code(pickCode);

        imqttService.sendMessageForNoticeToPick(bookOrder.getUser_id());

        bookOrderDao.updateBookOrder(bookOrder);
        containerDao.updateStatus(containerNumber,machineID,1);

        return pickCode;
    }

    @Override
    public List<BookOrder> queryOrderByMachineId(int machineId) {
        List<BookOrder> orderByMachineId = bookOrderDao.findOrderByMachineId(machineId, 1);
        return orderByMachineId;
    }

    @Override
    public BookOrderStatus getBookOrderStatus(String userId) {
        Integer to_pay = bookOrderDao.findOrderCountByUserId(userId, 0);
        Integer to_deliver = bookOrderDao.findOrderCountByUserId(userId, 1);
        Integer to_receive = bookOrderDao.findOrderCountByUserId(userId, 2);
        BookOrderStatus bookOrderStatus = new BookOrderStatus();
        bookOrderStatus.setTo_pay(to_pay);
        bookOrderStatus.setTo_deliver(to_deliver);
        bookOrderStatus.setTo_receive(to_receive);

        return bookOrderStatus;
    }

    @Override
    public String cancelBookOrder(String book_order_id) {
        BookOrder orderByOrderId = bookOrderDao.findOrderByOrderId(book_order_id);
        if(orderByOrderId==null){
            return BOOK_ORDER_IS_NULL;
        }else if(orderByOrderId.getOrder_status()!=0){
            return BOOK_ORDER_STATUS_ERROR;
        }else {
            BookOrder bookOrder = new BookOrder();
            bookOrder.setId(book_order_id);
            bookOrder.setOrder_status(6);
            bookOrderDao.updateBookOrder(bookOrder);
        }
        return CANCEL_BOOK_ORDER_SUCCESS;
    }

    @Override
    @Transactional
    public String applyForRefundBookOrder(String bookOrderId, String refund_reason) {
        BookOrder orderByOrderId = bookOrderDao.findOrderByOrderId(bookOrderId);
        if(orderByOrderId==null){
            return BOOK_ORDER_IS_NULL;
        }else if(orderByOrderId.getOrder_status()!=1){
            return BOOK_ORDER_STATUS_ERROR;
        }else {
            //修改订单状态
            BookOrder bookOrder = new BookOrder();
            bookOrder.setId(bookOrderId);
            bookOrder.setOrder_status(8);
            bookOrderDao.updateBookOrder(bookOrder);

            //添加信息到订单退款表
            RefundApply refundApply = new RefundApply();
            refundApply.setBool_order_id(bookOrderId);
            refundApply.setRefund_reason(refund_reason);
            refundApply.setRefund_time(String.valueOf(System.currentTimeMillis()));
            refundApplyDao.addRefundApply(refundApply);

            //机器容量加1
            MachineCache.addCapacity(orderByOrderId.getMachine_id());
        }
        return APPLY_REFUND_BOOK_ORDER_SUCCESS;
    }

    @Override
    public String cancelRefundBookOrder(String bookOrderId) {
        BookOrder orderByOrderId = bookOrderDao.findOrderByOrderId(bookOrderId);
        if(orderByOrderId==null){
            return BOOK_ORDER_IS_NULL;
        }else if(orderByOrderId.getOrder_status()==9){
            return REFUND_BOOK_ORDER_FINISH_ERROR;
        }else if(orderByOrderId.getOrder_status()!=8){
            return BOOK_ORDER_STATUS_ERROR;
        }else if(MachineCache.getCapacity(orderByOrderId.getMachine_id())<=0){
            return "非常抱歉,当前机器没有剩余容量,无法完成取消退款操作";
        }
        else{
            //修改订单状态
            BookOrder bookOrder = new BookOrder();
            bookOrder.setId(bookOrderId);
            bookOrder.setOrder_status(1);
            bookOrderDao.updateBookOrder(bookOrder);

            //删除订单退款表信息
            refundApplyDao.deleteRefundApplyByOrderId(bookOrderId);

            //机器容量减1
            MachineCache.reduceCapacity(orderByOrderId.getMachine_id());
        }
        return REFUSE_REFUND_BOOK_ORDER_SUCCESS;
    }

    @Override
    public PageInfo<RefundApply> queryBookOrderRefundApply(Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum,pageSize);
        List<RefundApply> all = refundApplyDao.findAll();
        PageInfo<RefundApply> refundApplyPageInfo = new PageInfo<>(all);
        return refundApplyPageInfo;
    }

    @Override
    @Transactional
    public void approveRefund(String bookOrderId, Integer refundApplyId) {
        refundApplyDao.updateStatus(refundApplyId,1);

        //修改订单状态
        BookOrder bookOrder = new BookOrder();
        bookOrder.setId(bookOrderId);
        bookOrder.setOrder_status(9);
        bookOrderDao.updateBookOrder(bookOrder);
    }

    @Override
    @Transactional
    public String refuseRefund(String bookOrderId, Integer refundApplyId) {
        BookOrder bookOrderById = queryOrderByOrderId(bookOrderId);
        if(MachineCache.getCapacity(bookOrderById.getMachine_id())<=0){
            return "机器容量不足";
        }

        refundApplyDao.updateStatus(refundApplyId,2);

        //修改订单状态
        BookOrder bookOrder = new BookOrder();
        bookOrder.setId(bookOrderId);
        bookOrder.setOrder_status(1);
        bookOrderDao.updateBookOrder(bookOrder);

        //机器容量减1
        MachineCache.reduceCapacity(bookOrderById.getMachine_id());

        return MessageConstant.Success.DO_SUCCESS_MESSAGE;
    }

    @Override
    public String determineAddBookOrder(Integer machineID, String bookOrderID) {
        //订单id检测
        BookOrder bookOrder = bookOrderDao.findOrderByOrderId(bookOrderID);
        String result = checkOrderId(machineID, bookOrder);
        if (result != null) return result;

        //生成门店取货码
        String pickCode = Utils.getStorePickCode(machineID);

        bookOrder.setOrder_status(2);
        bookOrder.setPick_code(pickCode);

        imqttService.sendMessageForNoticeToPick(bookOrder.getUser_id());

        bookOrderDao.updateBookOrder(bookOrder);

        return pickCode;
    }

    @Override
    public void determinePickUpOrder(BookOrder bookOrder) {
        bookOrder.setOrder_status(3);
        bookOrderDao.updateBookOrder(bookOrder);
    }

    @Override
    public BookOrder queryOrderByPickCode(Integer machineId, String pickCode) {
        BookOrder bookOrder = bookOrderDao.findOrderByPickCode(machineId,pickCode);
        if(bookOrder==null){
            return null;
        }
        List<BookCommodity> commodities = bookOrderDao.findBookCommodity(bookOrder.getId());
        bookOrder.setCommodities(commodities);
        return bookOrder;
    }

    @Override
    public Integer getBookCapacity(Integer machine_id) {
        return bookOrderDao.getBookCapacity(machine_id);
    }

    private String checkOrderId(Integer machineID, BookOrder bookOrder) {
        if (bookOrder == null){
            return "添加失败,没有找到订单ID";
        }
        if(bookOrder.getOrder_status()!=1){
            return "添加失败,不是待上货订单";
        }
        if(bookOrder.getMachine().getId()!=machineID){
            return "添加失败,该订单不属于本机器";
        }
        return null;
    }
}
